﻿/*              Copyright(c) 2008 Dave Sexton              *
 * http://www.codeplex.com/DocProject                      *
 * http://www.codeplex.com/DocProject/Project/License.aspx *
 ***********************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.ObjectModel;

namespace DaveSexton.DocToMaml
{
	internal class RuleCollection : KeyedCollection<RuleKey, IRule>
	{
		#region Public Properties
		public IRule this[string match]
		{
			get
			{
				return this[RuleKey.AnyKind(match)];
			}
		}
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="RuleCollection" /> class.
		/// </summary>
		public RuleCollection()
		{
		}
		#endregion

		#region Methods
		protected override RuleKey GetKeyForItem(IRule item)
		{
			return new RuleKey(item);
		}

		public bool Contains(string match)
		{
			return Contains(RuleKey.AnyKind(match));
		}

		protected override void ClearItems()
		{
			bool changed = Count > 0;

			base.ClearItems();

			if (changed)
				OnCollectionChange(EventArgs.Empty);
		}

		protected override void InsertItem(int index, IRule item)
		{
			if (item == null)
				throw new ArgumentNullException("item");

			if (Contains(new RuleKey(item)))
				throw new ArgumentException(Resources.Errors.DuplicateItemInCollection, "item");

			base.InsertItem(index, item);

			OnCollectionChange(EventArgs.Empty);
		}

		protected override void RemoveItem(int index)
		{
			base.RemoveItem(index);

			OnCollectionChange(EventArgs.Empty);
		}

		protected override void SetItem(int index, IRule item)
		{
			if (item == null)
				throw new ArgumentNullException("item");

			if (Contains(new RuleKey(item)))
			{
				for (int i = 0; i < Count; i++)
					if (i != index && RuleEqualityComparer.Default.Equals(this[i], item))
						throw new ArgumentException(Resources.Errors.DuplicateItemInCollection, "item");
			}

			base.SetItem(index, item);

			OnCollectionChange(EventArgs.Empty);
		}
		#endregion

		#region Events
		private readonly object CollectionChangeEventLock = new object();
		private EventHandler CollectionChangeEvent;

		/// <summary>
		/// Event raised when the collection changes.
		/// </summary>
		public event EventHandler CollectionChange
		{
			add
			{
				lock (CollectionChangeEventLock)
				{
					CollectionChangeEvent += value;
				}
			}
			remove
			{
				lock (CollectionChangeEventLock)
				{
					CollectionChangeEvent -= value;
				}
			}
		}

		/// <summary>
		/// Raises the <see cref="CollectionChange" /> event.
		/// </summary>
		/// <param name="e"><see cref="EventArgs" /> object that provides the arguments for the event.</param>
		protected virtual void OnCollectionChange(EventArgs e)
		{
			EventHandler handler = null;

			lock (CollectionChangeEventLock)
			{
				handler = CollectionChangeEvent;
			}

			if (handler != null)
				handler(this, e);
		}
		#endregion
	}
}
